package com.bizmda.bizsip.source.api;

import cn.hutool.core.util.IdUtil;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizResultEnum;

import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * Source层获取App调用接口
 *
 * @author shizhengye
 */
public class SourceClientFactory {
    private static final Map<String, Object> APP_SERVICE_CLIENT_CACHE = new HashMap<>();
    private static final Map<String, Class<?>> CLASS_CACHE = new HashMap<>();
    private static final ThreadLocal<String> traceIdThreadLocal = new ThreadLocal<>();

    private SourceClientFactory() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 获取App服务调用接口
     *
     * @param tClass       App服务的接口类（要求是interface）
     * @param appServiceId 应用服务ID
     * @param <T>          接口类泛型
     * @return 接口调用句柄
     */
    public static <T> T getAppServiceClient(Class<T> tClass, String appServiceId) {
        Class<?> clazz = CLASS_CACHE.get(appServiceId);
        if ((clazz != null) && (tClass == clazz)) {
            Object obj = APP_SERVICE_CLIENT_CACHE.get(appServiceId);
            return (T) obj;
        }
        final AppServiceClientProxy<T> appServiceClientProxy = new AppServiceClientProxy<>(tClass, appServiceId);
        Object obj = Proxy.newProxyInstance(tClass.getClassLoader(), new Class[]{tClass}, appServiceClientProxy);
        APP_SERVICE_CLIENT_CACHE.put(appServiceId, obj);
        CLASS_CACHE.put(appServiceId, tClass);
        return (T) obj;
    }

    /**
     * 创建TraceId，调用App服务交易的TracdId采用此TraceId
     * @return TraceId
     * @throws BizException BizException异常
     */
    public static String createTraceId() throws BizException {
        if (traceIdThreadLocal.get() != null) {
            throw new BizException(BizResultEnum.SOURCE_TRACEID_THREADLOCAL_NOTNULL);
        }
        String traceId = IdUtil.fastSimpleUUID();
        traceIdThreadLocal.set(traceId);
        return traceId;
    }

    /**
     * 获取创建的TraceId
     * @return TraceId
     */
    public static String getTraceId() {
        return traceIdThreadLocal.get();
    }

    /**
     * 清除创建的TraceId（如果在执行createTraceId()后调用App服务，务必执行此操作）
     */
    public static void removeTraceId() {
        traceIdThreadLocal.remove();
    }
}
